package org.jeecg.modules.friends.moments.service.impl;

import static java.util.stream.Collectors.toMap;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.MapUtils;
import org.jeecg.modules.friends.dao.MomentsLikeRecordsDAO;
import org.jeecg.modules.friends.model.MomentsLikeRecordsDO;
import org.jeecg.modules.friends.moments.dto.MomentsInfoDetailDTO;
import org.jeecg.modules.friends.moments.entity.Moments;
import org.jeecg.modules.friends.moments.mapper.MomentsMapper;
import org.jeecg.modules.friends.moments.param.LikeMomentsParam;
import org.jeecg.modules.friends.moments.param.MomentsPageRequest;
import org.jeecg.modules.friends.moments.param.PublishMomentsParam;
import org.jeecg.modules.friends.moments.service.IMomentsService;
import org.jeecg.modules.friends.momentspics.entity.MomentsPics;
import org.jeecg.modules.friends.momentspics.service.IMomentsPicsService;
import org.jeecg.modules.friends.service.rsp.MomentReviewRsp;
import org.jeecg.modules.friends.store.entity.MomentsReviewEntity;
import org.jeecg.modules.friends.store.mapper.MomentsReviewMapper;
import org.jeecg.modules.friends.store.wrapper.MomentsReviewQuery;
import org.jeecg.modules.friends.user.entity.User;
import org.jeecg.modules.friends.user.service.IUserService;
import org.jeecg.modules.friends.utils.ImageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;

import cn.hutool.core.collection.CollectionUtil;

/**
 * @Description: 动态信息表
 * @Author: jeecg-boot
 * @Date: 2024-05-15
 * @Version: V1.0
 */
@Service
public class MomentsServiceImpl extends ServiceImpl<MomentsMapper, Moments> implements IMomentsService {

    @Autowired
    private IMomentsPicsService momentsPicsService;

    @Autowired
    private MomentsMapper momentsMapper;


    @Autowired
    private MomentsLikeRecordsDAO momentsLikeRecordsDAO;
    @Autowired
    private MomentsReviewMapper momentsReviewMapper;
    @Lazy
    @Autowired
    private IUserService userService;

    @Override
    public IPage<MomentsInfoDetailDTO> queryMomentsPage(MomentsPageRequest momentsPageRequest, User visitor) {
        IPage<MomentsInfoDetailDTO> result = new Page<>();
        Page<Moments> page = new Page<>(momentsPageRequest.getPageNo(), momentsPageRequest.getPageSize());
        LambdaQueryWrapper<Moments> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Moments::getUserId, momentsPageRequest.getUserId());
        queryWrapper.orderByDesc(Moments::getAddTime);
        IPage<Moments> pageList = page(page, queryWrapper);
        result.setTotal(pageList.getTotal());
        result.setCurrent(pageList.getCurrent());
        result.setSize(pageList.getSize());
        result.setPages(pageList.getPages());
        if (pageList != null && CollectionUtils.isNotEmpty(pageList.getRecords())) {
            List<Long> momentIds = pageList.getRecords().stream().map(Moments::getId).collect(Collectors.toList());
            List<MomentsPics> momentsPics = momentsPicsService.selectByMomentsIds(momentIds);
            List<MomentsLikeRecordsDO> momentsLikeRecordsDOS =
                    momentsLikeRecordsDAO.queryByMomentsIdAndUserId(momentIds, visitor.getId());
            Map<Long, List<MomentsPics>> momentPicsMap = Maps.newHashMap();
            Map<Long, MomentsLikeRecordsDO> likeRecordsDOMap = Maps.newHashMap();
            if (CollectionUtils.isNotEmpty(momentsPics)) {
                momentPicsMap = momentsPics.stream().collect(Collectors.groupingBy(MomentsPics::getMomentsId));
            }
            if (CollectionUtils.isNotEmpty(momentsLikeRecordsDOS)) {
                likeRecordsDOMap = momentsLikeRecordsDOS.stream()
                        .collect(Collectors.toMap(MomentsLikeRecordsDO::getMomentsId, Function.identity()));
            }
            Map<Long, List<MomentsPics>> finalMomentPicsMap = momentPicsMap;
            Map<Long, MomentsLikeRecordsDO> finalLikeRecordsDOMap = likeRecordsDOMap;
            List<MomentsInfoDetailDTO> momentsInfoDetailDTOS = pageList.getRecords().stream().map(moments -> {
                MomentsInfoDetailDTO momentsInfoDetailDTO = new MomentsInfoDetailDTO();
                momentsInfoDetailDTO.setPublishTime(moments.getAddTime().getTime());
                momentsInfoDetailDTO.setMomentId(moments.getId());
                momentsInfoDetailDTO.setContent(moments.getContent());
                momentsInfoDetailDTO.setPicUrlList(finalMomentPicsMap.get(moments.getId()));
                momentsInfoDetailDTO.setLikeCount(moments.getLikeCount());
                momentsInfoDetailDTO.setHidden(moments.getHiddenFlag() != null && moments.getHiddenFlag() == 1);
                if (MapUtils.isNotEmpty(finalLikeRecordsDOMap)) {
                    MomentsLikeRecordsDO momentsLikeRecordsDO = finalLikeRecordsDOMap.get(moments.getId());
                    if (Objects.nonNull(momentsLikeRecordsDO) && momentsLikeRecordsDO.getStatus() == 0) {
                        momentsInfoDetailDTO.setClickLike(true);
                    } else {
                        momentsInfoDetailDTO.setClickLike(false);
                    }
                } else {
                    momentsInfoDetailDTO.setClickLike(false);
                }
                return momentsInfoDetailDTO;
            }).collect(Collectors.toList());
            // 设置评论数量和评论数据
            this.setReviewData(momentsInfoDetailDTOS);
            result.setRecords(momentsInfoDetailDTOS);
        }
        return result;
    }

    private void setReviewData(List<MomentsInfoDetailDTO> momentsInfoDetailDTOS) {

        List<Long> momentsIdList = ListUtils.emptyIfNull(momentsInfoDetailDTOS).stream()
                .map(MomentsInfoDetailDTO::getMomentId).collect(Collectors.toList());

        if (CollectionUtil.isEmpty(momentsIdList)) {
            return;
        }
        List<MomentsReviewEntity> momentsReviewEntities = momentsReviewMapper.listEntity(
                new MomentsReviewQuery()
                        .where
                        .momentsId().in(momentsIdList)
                        .end()
                        .orderBy
                        .id().desc().end()
        );

        Set<Long> userIds = ListUtils.emptyIfNull(momentsReviewEntities).stream()
                .map(MomentsReviewEntity::getUserId).collect(Collectors.toSet());
        if (CollectionUtil.isEmpty(userIds)) {
            return;
        }
        List<User> users = userService.listByIds(userIds);
        if (CollectionUtil.isEmpty(users)) {
            return;
        }
        Map<Long, User> userMap = ListUtils.emptyIfNull(users).stream()
                .collect(toMap(User::getId, Function.identity(), (oldValue, newValue) -> newValue));


        Map<Long, List<MomentsReviewEntity>> momentsReviewEntityMap =
                ListUtils.emptyIfNull(momentsReviewEntities).stream()
                        .collect(Collectors.groupingBy(MomentsReviewEntity::getMomentsId));
        if (MapUtils.isEmpty(momentsReviewEntityMap)) {
            return;
        }
        momentsInfoDetailDTOS.forEach(x -> {
            List<MomentsReviewEntity> momentsReviewEntities1 = momentsReviewEntityMap.get(x.getMomentId());
            if (CollectionUtil.isNotEmpty(momentsReviewEntities1)) {
                x.setReviewCount(momentsReviewEntities1.size());
                // 不展示所有评论
                momentsReviewEntities1 =
                        momentsReviewEntities1.subList(0, Math.min(momentsReviewEntities1.size(), 2));

                x.setReviewRsps(ListUtils.emptyIfNull(momentsReviewEntities1).stream()
                        .filter((y) -> {
                            User user = userMap.get(y.getUserId());
                            return user != null;
                        })
                        .map((element) -> {
                            MomentReviewRsp momentReviewRsp = new MomentReviewRsp();
                            momentReviewRsp.setReviewContent(element.getContent());
                            momentReviewRsp.setUserId(element.getUserId());
                            User user = userMap.get(element.getUserId());
                            if (user != null) {
                                momentReviewRsp.setHeadPicUrl(user.getHeadPicUrl());
                                momentReviewRsp.setGender(user.getGender());
                                momentReviewRsp.setAge(user.getBirthday());
                                momentReviewRsp.setCurrentResidence(user.getCurrentResidence());
                                momentReviewRsp.setNickName(element.getUserNickName());
                            }
                            return momentReviewRsp;
                        }).collect(Collectors.toList()));
            }
        });
    }

    @Override
    @Transactional
    public void publishMoments(PublishMomentsParam param, Long userId) {
        Moments moments = new Moments();
        moments.setUserId(userId);
        moments.setContent(param.getContent());
        moments.setLikeCount(0);
        moments.setAddTime(new Date());
        moments.setUpdateTime(new Date());
        Boolean flag = save(moments);
        if (flag && CollectionUtils.isNotEmpty(param.getPicUrls())) {
            List<MomentsPics> momentsPics = param.getPicUrls().stream().map(picUrl -> {
                MomentsPics momentsPic = new MomentsPics();
                momentsPic.setMomentsId(moments.getId());
                momentsPic.setPicUrl(ImageUtils.getCorrectImageUrl(picUrl.getPicUrl()));
                momentsPic.setOrderInfo(picUrl.getOrder());
                momentsPic.setStatus(0);
                momentsPic.setAddTime(new Date());
                momentsPic.setUpdateTime(new Date());
                return momentsPic;
            }).collect(Collectors.toList());
            momentsPicsService.saveBatch(momentsPics);
        }
    }

    @Override
    @Transactional
    public void deleteById(Long momentsId) {
        removeById(momentsId);
        momentsPicsService.removeByMomentsId(momentsId);
    }

    @Override
    @Transactional
    public void likeMoments(LikeMomentsParam param, Long id) {
        Moments moments = getById(param.getMomentsId());
        MomentsLikeRecordsDO momentsLikeRecordsDO = momentsLikeRecordsDAO.queryOneByMoments(param.getMomentsId(), id);
        if (moments != null) {
            if (param.getOperateType() == 1) {
                momentsMapper.addLikeCount(param.getMomentsId());
                if (momentsLikeRecordsDO == null) {
                    momentsLikeRecordsDO = new MomentsLikeRecordsDO();
                    momentsLikeRecordsDO.setLikeUserId(id);
                    momentsLikeRecordsDO.setMomentsId(param.getMomentsId());
                    momentsLikeRecordsDO.setAddTime(new Date());
                    momentsLikeRecordsDO.setStatus(0);
                    momentsLikeRecordsDO.setUpdateTime(new Date());
                    momentsLikeRecordsDAO.insert(momentsLikeRecordsDO);
                } else {
                    momentsLikeRecordsDO.setStatus(0);
                    momentsLikeRecordsDAO.update(momentsLikeRecordsDO);
                }

            }
            if (param.getOperateType() == 2) {
                if (Objects.isNull(momentsLikeRecordsDO)) {
                    return;
                }
                momentsLikeRecordsDO.setStatus(1);
                momentsLikeRecordsDAO.update(momentsLikeRecordsDO);
                if (moments.getLikeCount() != null && moments.getLikeCount() > 0) {
                    momentsMapper.minusLikeCount(param.getMomentsId());
                }

            }
        }
    }

    @Override
    public void deleteByUserId(Long userId) {
        LambdaQueryWrapper<Moments> momentsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        momentsLambdaQueryWrapper.eq(Moments::getUserId, userId);
        List<Moments> moments = momentsMapper.selectList(momentsLambdaQueryWrapper);
        for (Moments moment : moments) {
            deleteById(moment.getId());
        }
    }

}
